import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
import { Quaternion, Vector3 } from '@babylonjs/core/Maths/math.vector';
import { DefaultStage } from '../../default-stage';
import { AnimationFrame, ITimer } from 'babylon-lib/index';
import { WebXRCamera } from '@babylonjs/core/XR/webXRCamera';
import { Axis } from '@babylonjs/core/Maths/math.axis';
import { Helper } from 'babylon-lib/tool/helper';


abstract class AbstractCharacter {

    private _bindReq: ITimer = {};

    protected _container: TransformNode;

    public readonly stage: DefaultStage;

    constructor(stage: DefaultStage) {
        this.stage = stage;
        this._container = new TransformNode('uav-container', stage.mainScene);
        this._container.rotationQuaternion = Quaternion.Identity();
        this.bindToCamera(stage);
    }

    public get container(): TransformNode {
        return this._container;
    }

    protected abstract setModel(stage: DefaultStage): void;

    private bindToCamera(stage: DefaultStage): void {
        const dir = new Vector3();
        const ref = new Vector3();
        const rot = Quaternion.Identity();

        this._bindReq.observable = stage.mainScene.onBeforeCameraRenderObservable;
        AnimationFrame.request(() => {
            const camera = (stage.mainCamera instanceof WebXRCamera) ? stage.mainCamera.rigCameras[0] : stage.mainCamera;
            this._container.position.copyFrom(camera.position);

            Helper.cameraDirection(camera, dir);
            dir.y = 0;
            dir.normalize();
            ref.set(0, 0, 1);
            ref.applyRotationQuaternionInPlace(this._container.rotationQuaternion!);
            ref.normalize();
            const ang = Vector3.GetAngleBetweenVectors(ref, dir, Axis.Y) * 0.02;
            Quaternion.FromEulerAnglesToRef(0, ang, 0, rot)
            this._container.rotationQuaternion!.multiplyInPlace(rot);
        }, 0, 200, this._bindReq);

    }

}


export { AbstractCharacter };